
//package cfu_main.fir;
/*
 * This file creates the array of 8x8 CFU (total 64 CFUs). It verifies the functionality od FIR filter
 * Filter configuration: 
 * 		LCF = ; HCF = ;Sampling frequency =;Taps = 25; Number of channels = 1;
 * 		
 * 
 * 
 */

import java.io.File;

//import java.io.*;
//import java.util.*;





public class ISS_SIMD_FIR_16points_256samples
{

	/*Input arguments to this class will be in the following order
	 * 0- Instruction
	 * 1- 1st input register index 
	 * 2- 2nd input register index; pass null if not required
	 * 3- 3rd input register index; pass null if not required
	 * 4- Output register index
	 * 5- Shift offset	
	 */

	/*public static String no_cfu_row_string;
    public static String no_cfu_column_string ;
    public static String no_taps_string;
    public static String no_samples_string;
    public static String no_channels_string;*/

	public static int no_cfu_row_int ;
	public static int no_cfu_column_int ;
	public static int no_taps_int;
	public static int no_samples_int;
	public static int no_channels_int;
	public static int total_cfu,no_cfu_per_channel,unused_cfu;

	public  Cfu [][] Cfu_Array = new Cfu[8][8];
	
	
	

	public static File in_data_file;
	public static String file_path = "";
	public Ram fir_ram;
	static int ram_size = 2048;
	public static int ram_read_index;
	
	//Because we will start from reverse
	public static int last_ram_read_index = 2*no_taps_int;
	
	//Instructions
	public static final int NOP = 0,
							ADD = 1,
							SHIFT_LEFT = 2,
							SHIFT_RIGHT = 3,
							MAC = 4,
							ADM = 5
							;
	
	public static final int fir_scaling_factor = 15;



	//Cfu[][] Cfu_Array = new Cfu[no_cfu_row][no_cfu_column];
	//Cfu cfu1 = new Cfu(1,0,1,2,3,0);

	public void Create_Cfu_Array()
	{
		//Creating array of 8x8 CFUs

		//Cfu_Array = new Cfu[no_cfu_row_int];

		//Initializing with default constructors
		for (int i=0;i<no_cfu_row_int;i++)
		{
			for(int j=0;j<no_cfu_column_int;j++)
			{

				Cfu_Array[i][j] = new Cfu();
			}

		}
	}


	public void Create_RAM()
	{
		fir_ram = new Ram(ram_size);
		fir_ram.Load_Coefficients();
		fir_ram.Load_Data();

	}

	public void Load_Coefficients_into_CFUs()
	{
		
		/*
		 * Note: Channels are mapped horizontally
		 */
		
		/*
		 *It is assumed that FIR filter coefficients are stored in the initial part of the RAM
		 *
		 */
		
		
		int cfu_row_index = 0, cfu_column_index =0;
		for (int channelNo=0;channelNo<no_channels_int; channelNo++)
		{
			/*
			 * We load same coefficient in no_cfu_per_channel for multiple channel processing.
			 * So, we will start loading coefficients again 
			 */
			
			ram_read_index = 0;
			for (int cfuNo=0;cfuNo<no_cfu_per_channel;cfuNo++)
			{	
				if (cfu_column_index == no_cfu_column_int -1)
				{
					//Move to next row
					cfu_row_index ++; 
					//Start from the first column of the next row
					cfu_column_index = 0; 

				}
				else
				{
			//	Cfu_Array[cfu_row_index][cfu_column_index].update_register(0, fir_ram.ram[ram_read_index]);
				
				//increase column index and move forward to next CFU
				cfu_column_index++;
				
				//Read next data from RAM
				ram_read_index++;
				}
			}
		}
	}
	
	public void Load_Data_into_CFUs()
	{
		
		/*
		 * Note: Channels are mapped horizontally
		 */
		
		/*
		 *It is assumed that FIR filter coefficients are stored in the initial part of the RAM
		 *
		 */
		
		//Start reading Data from Ram next from the last coefficient
		ram_read_index = last_ram_read_index;
		int cfu_row_index = 0, cfu_column_index =0;
		for (int channelNo=0;channelNo<no_channels_int; channelNo++)
		{
			
			for (int cfuNo=0;cfuNo<no_cfu_per_channel;cfuNo++)
			{	
				if (cfu_column_index == no_cfu_column_int -1 )
				{
					//Move to next row
					cfu_row_index ++; 
					//Start from the first column of the next row
					cfu_column_index = 0; 

				}
				else
				{
				//Cfu_Array[cfu_row_index][cfu_column_index].update_register(1, fir_ram.ram[ram_read_index]);
				
				//increase column index and move forward to next CFU
				cfu_column_index++;
				
				//Read next data from RAM
				ram_read_index++;
				}
			}
		}
		
		/*
		 * Store the index of last Data loaded in the CFU so that next round of the 
		 * loading can be started from there.
		 */
		
		last_ram_read_index = ram_read_index;
		
	}
	
	private void Configure_CFUs()
	{
		int cfu_row_index = 0, cfu_column_index =0;
		//Configure CFUs for MAC operations
		
		for (int channelNo=0;channelNo<no_channels_int; channelNo++)
		{
			
			for (int cfuNo=0;cfuNo<no_cfu_per_channel;cfuNo++)
			{	
				if (cfu_column_index == no_cfu_column_int -1 )
				{
					//Move to next row
					cfu_row_index ++; 
					//Start from the first column of the next row
					cfu_column_index = 0; 

				}
				
				else
				{
				//Cfu_Array[cfu_row_index][cfu_column_index].Cfu_initialize(MAC,0,1, 2, 3, 0);
				
				//increase column index and move forward to next CFU
				cfu_column_index++;
				}
				
			}
		}
		
//		//Configure CFUs for final addition operation
//		cfu_row_index = 1;
//		for (int channelNo=0;channelNo<no_channels_int; channelNo++)
//		{
//			
//				Cfu_Array[cfu_row_index][no_cfu_column_int-1].Cfu_initialize(ADD,0,1, 2, 3, 0);
//				cfu_row_index = cfu_row_index+2;
//			
//		}
//			
//		//Configure CFUs for shift operation
//		cfu_row_index = 0;
//		for (int channelNo=0;channelNo<no_channels_int; channelNo++)
//		{
//			
//				Cfu_Array[cfu_row_index][no_cfu_column_int-1].Cfu_initialize(SHIFT_RIGHT,0,1, 2, 3, fir_scaling_factor);
//				cfu_row_index = cfu_row_index+2;
//			
//		}
	}
	
	private void Run_CFUs()
	{
		
		int cfu_row_index = 0, cfu_column_index =0;
		
		//Run all MAC units first
		
		//cycle 1
		
		//Configure CFUs
		Cfu_Array[0][0].update_register(1, fir_ram.ram[2*no_taps_int]);
		Cfu_Array[1][0].update_register(1, fir_ram.ram[2*no_taps_int + no_cfu_column_int-1]);
		//Cfu_Array[1][0].update_register(1,4);
		
		
		//Run CFUs
		Cfu_Array[0][0].Cfu_initialize(MAC, 0, 1, 2, 3, 0);
		Cfu_Array[1][0].Cfu_initialize(MAC, 0, 1, 2, 3, 0);
		
		
		Cfu_Array[0][0].start_CFU();
		Cfu_Array[1][0].start_CFU();
//		
		//Cfu_Array[0].update_register(1,4);
		//Cfu_Array[1].update_register(1,4);
		for (int x=0;x<8;x++)
		{
			for (int y=0;y<8;y++)
			{
				for (int i=0;i<4;i++)
					System.out.println(Cfu_Array[x][y].register_array[i]);
			}
		}
//		for (int x=0;x<Cfu_Array[1].register_array.length;x++)
//		System.out.println(Cfu_Array[0].register_array[x]);
//		
//		for (int x=0;x<Cfu_Array[1].register_array.length;x++)
//			System.out.println(Cfu_Array[1].register_array[x]);
		
		//for (int x=0;x<Cfu_Array[1][0].register_array.length;x++)
			//System.out.println(Cfu_Array[1][0].register_array[x]);
		
		
		
	}
	
	private void Get_Output()
	{
	
	}
	
	
	public void run_fir_16taps_256_samples_4channels()
	//public static void main(String args[])
	{
		//		//		Cfu_Array[0][1].update_register(1, 65);
		//		//      Cfu_Array[0][1].update_register(0, 65);
		//		//		Cfu_Array[0][0].Cfu_initialize(1, 0, 1, 2, 3, 0);
		//		//		Cfu_Array[0][0].start_CFU();
		

		//RAM check
		//for (int i=0;i<fir_ram.ram.length ;i++)
		for (int i=0;i<fir_ram.ram_array_index;i++)
		{
			System.out.println("ram[" + i + "] = " + fir_ram.ram[i]);
		}
		
		/*
		 * The process is performed in following steps:
		 * 1) Load all the coefficients in to CFUs
		 * 2) Load all CFUs with data
		 * 3) Initialize/Configure CFUs	
		 * 4) Perform operation and collect final answer
		 * 5) Put final answer in RAM and finally in text file
		 * 
		 */
		
		//Step 1) Load all the coefficients in to CFUs
		//Load_Coefficients_into_CFUs();
		
		//Step 2) Load all CFUs with data
		//Load_Data_into_CFUs();
		
		//Step 3) Initialize/Configure CFUs
		//Configure_CFUs();
		
		//Step 4) Perform operation and collect final answer
		Run_CFUs();
		
		//Step 5) Put final answer in RAM and finally in text file
		Get_Output();
		
		
	}



	//	public static void main (String[] args) 
	//	{
	//		/*		Ram ram_fir = new Ram;
	//
	//		String ram_size_string = JOptionPane.showInputDialog(null,"Enter RAM size:");
	//		int ram_size_int = Integer.parseInt(ram_size_string);
	//
	//		ram_fir.Ram(ram_size_int);*/
	//		//JOptionPane.showMessageDialog(null,"Jai Sairam..The program started...!");
	//		//		java.awt.EventQueue.invokeAndWait(new Runnable() {
	//		//            @Override
	//		//            public void run() {
	//		//                JOptionPane.showMessageDialog(null,"Jai Sairam..The program started 1.1...!");
	//		//                new ISS_SIMD_FIR_form().setVisible(true);
	//		//                JOptionPane.showMessageDialog(null,"Jai Sairam..The program started 1.2...!");
	//		//            }
	//		//        });
	//		/*no_cfu_row_string = JOptionPane.showInputDialog("Please, enter no of rows for CFU array");
	//		no_cfu_column_string = JOptionPane.showInputDialog("Please, enter no of columns for CFU array");
	//		no_taps_string = JOptionPane.showInputDialog("Please, enter no of taps in  FIR filter");
	//		no_samples_string = JOptionPane.showInputDialog("Please,enter no of samples to process");
	//		no_channels_string =  JOptionPane.showInputDialog("Please, enter no of channels you want process in parallel");*/
	//
	//		/*no_cfu_row_int = Integer.parseInt(no_cfu_row_string);
	//		no_cfu_column_int = Integer.parseInt(no_cfu_column_string);
	//		no_taps_int = Integer.parseInt(no_taps_string);
	//		no_samples_int = Integer.parseInt(no_samples_string);
	//		no_channels_int = Integer.parseInt(no_channels_string);*/
	//
	//		/*total_cfu = no_cfu_column_int * no_cfu_row_int;
	//		no_cfu_per_channel =  total_cfu / no_channels_int;
	//		unused_cfu = total_cfu - (no_cfu_per_channel * no_channels_int);*/
	//
	//		//JOptionPane.showMessageDialog(null, "no_cfu_per_channel= " + no_cfu_per_channel+"channels "+no_channels_int+" unused" + unused_cfu );
	//
	//
	//
	//
	//		//		Cfu_Array[0][1].update_register(1, 65);
	//		//        Cfu_Array[0][1].update_register(0, 65);
	//		//		Cfu_Array[0][0].Cfu_initialize(1, 0, 1, 2, 3, 0);
	//		//		Cfu_Array[0][0].start_CFU();
	//
	//		System.exit(0);
	//	}
	//


}

